/*
 * @Author: 0x9DEFA478
 * @Date: 2025-08-08 22:55:41
 * @LastEditTime: 2025-10-24 22:53:04
 * @LastEditors: 0x9DEFA478
 * @Description: 指针对象定义
 *               指针必须是通过new产生(或者等效的方式)，能够调用delete
 *               多个指针对象能够容纳同一个指针
 *               一个指针只能构造成H::Pointer一次 否则会出现重复析构的问题
 *               指针对象被移动后将变得不可用, 只能被赋值或者被析构
 * 
 */
#ifndef hH_Pointer_HPP_
#define hH_Pointer_HPP_
#include <functional>
#include <initializer_list>
#include <utility>
#include <type_traits>
#include "H_Atomic.hpp"
#include "Utility/H_Iterator.hpp"
#if defined(cH_Assert_AccessViolation)&&(cH_Assert_AccessViolation!=0)
#include <stdexcept>
#include "SystemUtility/C_iostream.hpp"
#endif




namespace H{

#if __cplusplus >= 202000L
  template<typename ObjectType,Atomic::is_Count CountType=EmptyCount_usize>
#else
  template<typename ObjectType,typename CountType=EmptyCount_usize>
#endif
  class Pointer{

    public:
      using Type=std::remove_cv_t<ObjectType>;

      using TypePointer=Type*;
      using TypeConstPointer=const Type*;

      using DeleteFunction_t=std::function<void(TypePointer)>;

      using Iterator=H::Iterator::Array<Type>;
      using Reverse_Iterator=H::Iterator::Reverse_Array<Type>;

    private:
      class ReferenceRecorder{
        public:
          template<typename T_Call>
          ReferenceRecorder(TypePointer Pointer,T_Call&& deleteFunction,usize Length):pointer(Pointer),length(Length),referenceCount(0),deleteFunction(deleteFunction){}
          ~ReferenceRecorder(){
            if(pointer!=nullptr){
              deleteFunction(pointer);
            }
          }
          ReferenceRecorder(const ReferenceRecorder&)=delete;
          ReferenceRecorder(ReferenceRecorder&&)=delete;

          Type& operator[](std::ptrdiff_t Index)const noexcept{
#if defined(cH_Assert_AccessViolation)&&(cH_Assert_AccessViolation!=0)
            if((pointer==nullptr)||(Index<0)||(((H::usize)Index)>=Length())){
              H::cerr<<"H::Pointer发现越界访问 Index="<<Index<<" Size="<<Length()<<std::endl;
              std::terminate();
            }
#endif
            return pointer[Index];
          }

          TypePointer GetPointer()const noexcept{return pointer;}
          usize Length()const noexcept{return length;}
          TypePointer GetEndPointer()const noexcept{return pointer+length;}

          ReferenceRecorder* Increase()noexcept{
            referenceCount.increment(1);
            return this;
          }
          bool Decrease()noexcept{
            if(referenceCount.decrement(1)==0){
              return true;
            }
            return false;
          }


          ReferenceRecorder* Clone()const{
            if(pointer==nullptr){
              return new ReferenceRecorder(nullptr,DeleteArray,0);
            }
            auto r=new ReferenceRecorder(new Type[length],DeleteArray,length);
            for(usize i=0;i<length;i++){
              (*r)[i]=pointer[i];
            }
            return r;
          }
          ReferenceRecorder* Clone(usize NewLength)const{
            if(NewLength<1){
              return new ReferenceRecorder(nullptr,DeleteArray,0);
            }
            auto r=new ReferenceRecorder(new Type[NewLength],DeleteArray,NewLength);
            if(NewLength>length){
              NewLength=length;
            }
            for(usize i=0;i<NewLength;i++){
              (*r)[i]=pointer[i];
            }
            return r;
          }


          static void Equal_Copy(ReferenceRecorder** RR_Dst,ReferenceRecorder* const* RR_Src)noexcept{
            auto dst=*RR_Dst;
            auto src=*RR_Src;
            if(*RR_Dst==src){
              return;
            }
            if((dst!=nullptr)&&dst->Decrease()){
              delete dst;
            }
            *RR_Dst=src->Increase();
          }
          static void Equal_Move(ReferenceRecorder** RR_Dst,ReferenceRecorder** RR_Src)noexcept{
            auto dst=*RR_Dst;
            auto src=*RR_Src;
            if(*RR_Dst==src){
              return;
            }
            if((dst!=nullptr)&&dst->Decrease()){
              delete dst;
            }
            *RR_Dst=src;
            *RR_Src=nullptr;
          }


        private:
          const TypePointer pointer;
          const usize length;
          CountType referenceCount;
          const DeleteFunction_t deleteFunction;
      };
      
    public:
      class Const{
        public:
          using Iterator=H::Iterator::Array<const Type>;
          using Reverse_Iterator=H::Iterator::Reverse_Array<const Type>;
        public:
          Const():rr(new ReferenceRecorder(nullptr,DeleteObject,0)){}
          ~Const(){
            if(rr!=nullptr){
              if(rr->Decrease()){
                delete rr;
              }
            }
          }

          Const(const Const& CP)noexcept:rr(CP.rr->Increase()){}
          Const(Const&& CP)noexcept:rr(CP.rr){CP.rr=nullptr;}
          Const(const Pointer& P)noexcept:rr(P.rr->Increase()){}
          Const(Pointer&& P)noexcept:rr(P.rr){P.rr=nullptr;}

          Const& operator=(const Const& CP)noexcept{ReferenceRecorder::Equal_Move(&rr,&CP.rr);return *this;}
          Const& operator=(Const&& CP)noexcept{ReferenceRecorder::Equal_Move(&rr,&CP.rr);return *this;}
          Const& operator=(const Pointer& P)noexcept{ReferenceRecorder::Equal_Copy(&rr,&P.rr);return *this;}
          Const& operator=(Pointer&& P)noexcept{ReferenceRecorder::Equal_Move(&rr,&P.rr);return *this;}

          operator TypeConstPointer()const noexcept{return this->rr->GetPointer();}
          TypeConstPointer operator->()const noexcept{return this->rr->GetPointer();}
          TypeConstPointer GetPointer()const noexcept{return this->rr->GetPointer();}

          const Type& operator*()const noexcept{return *this->rr->GetPointer();}
          const Type& operator[](std::ptrdiff_t Index)const noexcept{return (*this->rr)[Index];}

          usize Length()const noexcept{return rr->Length();}

          operator bool()const noexcept{return rr->GetPointer()!=nullptr;}
          bool operator!()const noexcept{return rr->GetPointer()==nullptr;}

          bool operator==(TypeConstPointer pointer)const noexcept{return pointer==this->rr->GetPointer();}
          bool operator!=(TypeConstPointer pointer)const noexcept{return pointer!=this->rr->GetPointer();}
          bool operator==(const Const& CP)const noexcept{return CP.rr==this->rr;}
          bool operator!=(const Const& CP)const noexcept{return CP.rr!=this->rr;}
          bool operator==(const Pointer& P)const noexcept{return P.rr==this->rr;}
          bool operator!=(const Pointer& P)const noexcept{return P.rr!=this->rr;}
          friend bool operator==(const Pointer& P,const Const& CP)noexcept{return CP==P;}
          friend bool operator!=(const Pointer& P,const Const& CP)noexcept{return CP!=P;}

          int compare(const Pointer& P)const noexcept{
            if(rr<P.rr){
              return -1;
            }else if(rr>P.rr){
              return 1;
            }
            return 0;
          }
          bool operator<(const Pointer& P)const noexcept{return compare(P)<0;}
          bool operator>(const Pointer& P)const noexcept{return compare(P)>0;}

          Pointer Clone()const{
            return Pointer(rr->Clone());
          }
          Pointer Clone(usize NewLength)const{
            return Pointer(rr->Clone(NewLength));
          }

          void Set_nullptr(){
            if(rr!=nullptr){
              if(rr->Decrease()){
                delete rr;
              }
            }
            rr=new ReferenceRecorder(nullptr,DeleteObject,0);
          }
          
          Iterator begin()const noexcept{return Iterator(rr->GetPointer());}
          Iterator end()const noexcept{return Iterator(rr->GetEndPointer());}
          Reverse_Iterator rbegin()const noexcept{return Reverse_Iterator(rr->GetEndPointer()-1);}
          Reverse_Iterator rend()const noexcept{return Reverse_Iterator(rr->GetPointer()-1);}

          static Pointer Cast(const Const& CP)noexcept{return Pointer(CP.rr->Increase());};
          static Pointer Cast(Const&& CP)noexcept{auto r=Pointer(CP.rr);CP.rr=nullptr;return r;};
        
        private:
          ReferenceRecorder* rr;
      };

    public:
      template<typename T_Call=DeleteFunction_t>
      explicit Pointer(TypePointer RawPointer=nullptr,T_Call&& DeleteFunction=DeleteObject,usize Length=1){
#if __cplusplus >= 202000L
        static_assert(std::is_invocable_v<T_Call,TypePointer>,"DelectFunction args invalid");
#endif
        if(RawPointer==nullptr){
          Length=0;
        }
        rr=new ReferenceRecorder(RawPointer,std::forward<T_Call>(DeleteFunction),Length);
      }
      ~Pointer(){
        if(rr!=nullptr){
          if(rr->Decrease()){
            delete rr;
          }
        }
      }


      template<typename... T_Arg>
      static Pointer New(T_Arg&&... Args){return Pointer(new Type(std::forward<T_Arg>(Args)...));}

      template<typename T>
      static Pointer New(std::initializer_list<T>&& initializer_list){return Pointer(new Type(std::move(initializer_list)));}

      static Pointer Array(usize Length){
        if(Length==0){
          return Pointer(nullptr,DeleteArray);
        }
        return Pointer(new Type[Length],DeleteArray,Length);
      }

      static void DeleteObject(TypePointer pointer){delete pointer;}
      static void DeleteArray(TypePointer pointer){delete[] pointer;}
      

      Pointer(const Pointer& P)noexcept:rr(P.rr->Increase()){}
      Pointer(Pointer&& P)noexcept:rr(P.rr){P.rr=nullptr;}

      Pointer& operator=(const Pointer& P)noexcept{ReferenceRecorder::Equal_Copy(&rr,&P.rr);return *this;}
      Pointer& operator=(Pointer&& P)noexcept{ReferenceRecorder::Equal_Move(&rr,&P.rr);return *this;}

      operator TypePointer()const noexcept{return rr->GetPointer();}
      TypePointer operator->()const noexcept{return rr->GetPointer();}
      TypePointer GetPointer()const noexcept{return rr->GetPointer();}

      Type& operator*()const noexcept{return *rr->GetPointer();}
      Type& operator[](std::ptrdiff_t Index)const noexcept{return (*rr)[Index];}

      usize Length()const noexcept{return rr->Length();}

      operator bool()const noexcept{return rr->GetPointer()!=nullptr;}
      bool operator!()const noexcept{return rr->GetPointer()==nullptr;}

      bool operator==(TypeConstPointer pointer)const noexcept{return pointer==rr->GetPointer();}
      bool operator!=(TypeConstPointer pointer)const noexcept{return pointer!=rr->GetPointer();}
      bool operator==(const Pointer& P)const noexcept{return P.rr==rr;}
      bool operator!=(const Pointer& P)const noexcept{return P.rr!=rr;}

      int compare(const Pointer& P)const noexcept{
        if(rr<P.rr){
          return -1;
        }else if(rr>P.rr){
          return 1;
        }
        return 0;
      }
      bool operator<(const Pointer& P)const noexcept{return compare(P)<0;}
      bool operator>(const Pointer& P)const noexcept{return compare(P)>0;}

      void Set_nullptr(){
        if(rr!=nullptr){
          if(rr->Decrease()){
            delete rr;
          }
        }
        rr=new ReferenceRecorder(nullptr,DeleteObject,0);
      }

      Pointer Clone()const{
        return Pointer(rr->Clone());
      }
      Pointer Clone(usize NewLength)const{
        return Pointer(rr->Clone(NewLength));
      }

      Iterator begin()const noexcept{return Iterator(rr->GetPointer());}
      Iterator end()const noexcept{return Iterator(rr->GetEndPointer());}
      Reverse_Iterator rbegin()const noexcept{return Reverse_Iterator(rr->GetEndPointer()-1);}
      Reverse_Iterator rend()const noexcept{return Reverse_Iterator(rr->GetPointer()-1);}

    private:
      explicit Pointer(ReferenceRecorder* rr)noexcept:rr(rr){}

    private:
      ReferenceRecorder* rr;
  };

  template<typename ObjectType>
  using PointerShare=Pointer<ObjectType,Count_usize>;

}




#endif //hH_Pointer_HPP_
